import re

from django.core.exceptions import ObjectDoesNotExist
from django import newforms as forms
from django.contrib.auth.models import User

from django.utils.translation import gettext_lazy as _

class RegistrationForm(forms.Form):
    username = forms.CharField(label='Username', max_length=30)
    email = forms.EmailField(label='Email')
    password1 = forms.CharField(
        label='Password',
        widget=forms.PasswordInput()
        )
    password2 = forms.CharField(
        label='Password (Again)',
        widget=forms.PasswordInput()
        )
    
    def clean_password2(self):
        if 'password1' in self.clean_data:
            password1 = self.clean_data['password1']
            password2 = self.clean_data['password2']
            if password1 == password2:
                return password2
        ## This is as it was in Hourieh's example, but I 
        ## personally would prefer to raise an 'invalid password'
        ## or some such here, as it is raised whether the problem
        ## is caused by a  mis-match or by some other problem such
        ## as non-alphanumeric characters or some such.
        raise forms.ValidationError('Passwords do not match.')
    
    def clean_username(self):
        username = self.clean_data['username']
        if not re.search(r'^\w+$', username):
            raise forms.ValidationError('Username can only contain alphanumeric characters and the underscore.')
        try:
            User.objects.get(username=username)
        ## First check specifically for the ObjectDoesNotExist exception: we
        ## expect this if the username is still free. Ie the exception is a 
        ## 'sentinel value' in this case, not an actual error-condition.  
        except ObjectDoesNotExist:
            return username
        ## Now catch any other errors, and if there are any, re-raise them. 
        ## This allows us to pass on other error conditions to outer code
        ## for handling. I'm not sure if this try and re-raise are strictly 
        ## necessary, as the earlier handler was so specific, but until I'm
        ## sure I'll put this in to be on the safe side.
        except:
            raise
        ## If we get to here, there was no exception of any kind raised by the
        ## attempt to thet the user object with that name. So, the user object 
        ## exists, and thus that username is already taken. Signal this by 
        ## raising a form validation exception with an appropriate message.
        raise forms.ValidationError('Username is already taken.')
        
class BookmarkSaveForm(forms.Form):
  url = forms.URLField(
    label='URL',
    widget=forms.TextInput(attrs={'size': 64})
  )
  title = forms.CharField(
    label='Title',
    widget=forms.TextInput(attrs={'size': 64})
  )
  tags = forms.CharField(
    label='Tags',
    required=False,
    widget=forms.TextInput(attrs={'size': 64})
  )

class SearchForm(forms.Form):
  query = forms.CharField(
    label='Enter a keyword to search for',
    widget=forms.TextInput(attrs={'size': 32})
  )
  
class FriendInviteForm(forms.Form):
  name = forms.CharField(label=_("Friend's Name"))
  email = forms.EmailField(label=_("Friend's Email"))
  